package com.welike.shibo.filter;


import com.welike.shibo.eneity.JsonResult;
import com.welike.shibo.enums.ResultEnum;
import com.welike.shibo.enums.TokenStatus;
import com.welike.shibo.utils.Constants;
import com.welike.shibo.utils.JwtUtil;
import com.welike.shibo.utils.ResultUtils;
import lombok.extern.slf4j.Slf4j;
import org.json.JSONObject;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * jwt过滤器
 *
 * @author fangyu
 * @version v1.0.0
 * @since 2019-08-18 23:20
 */
@Slf4j
//@Component
public class JwtFilter implements Filter {

    /**
     * 排除拦截的请求, 这些请求不需要用到Jwt
     */
    private String[] excludedPages = {"/login", "/api/user/sms", "/api/user/register", "/api/user/login",
            "/swagger-ui.html",
            "/webjars/springfox-swagger-ui/swagger-ui.css?v=2.9.2"};

    private JwtUtil jwtUtil = new JwtUtil();

    private static final PathMatcher pathMatcher = new AntPathMatcher();

    /**
     * 过滤器初始化
     *
     * @param filterConfig
     * @throws ServletException
     */
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.info("JwtFilter init ...");
    }



    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        // 类型强制转换
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
        try {
            // 排除/api请求
            if (!isProtectedUrl(httpServletRequest)) {
                return;
            }
            // 遍历白名单List中的页面
            for (String page : excludedPages) {
                // 如果请求的URI == page页面，则不进行拦截过滤操作，直接放行
                if (httpServletRequest.getRequestURI().equals(page)) {
                    filterChain.doFilter(httpServletRequest, httpServletResponse);
                    return;
                }
            }
            // 获取HTTP请求中头部中的token
            String token = httpServletRequest.getHeader(Constants.TOKEN_HEADER);
            TokenStatus tokenStatus = jwtUtil.verifyToken(token);
            switch (tokenStatus) {
                // 有效
                case VALID:
                    // 一、获取Token中的username信息
                    String user = jwtUtil.getUserNameFromToken(token);
                    // 二、在Request请求中加入验证用户的信息
                    httpServletRequest.setAttribute(Constants.LOGIN_USER, user);
                    // 三、放入Request请求，执行拦截过滤操作
                    filterChain.doFilter(httpServletRequest, httpServletResponse);
                    break;
                // 过期
                case EXPIRED:
                    accessDeny(httpServletResponse, 2);
                    break;
                // 其他均无效(包括TokenStatus.INVALID)
                default:
                    accessDeny(httpServletResponse, 1);
                    break;
            }

        } catch (Exception e){
            log.error("JwtFilter doFilter Exception: {}", e.getMessage());
            accessDeny(httpServletResponse, 1);
        }
    }

    /**
     * token 校验提示
     * @param response http返回结果
     * @param type 1无效, 2过期
     */
    private void accessDeny(HttpServletResponse response, int type) {
        PrintWriter writer = null;
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html; charset=utf-8");
        try {
            writer = response.getWriter();
            JsonResult jsonResult = new JsonResult();
            if (1 == type){
                jsonResult = ResultUtils.result(ResultEnum.TOKEN_INVALID.getCode(), "", null);
            } else if (2 == type){
                jsonResult = ResultUtils.result(ResultEnum.TOKEN_EXPIRED.getCode(), "", null);
            }
            JSONObject jsonObject = new JSONObject(jsonResult);
            writer.print(jsonObject);
        } catch (IOException e) {
            log.error("JwtFilter accessDeny IOException: {}", e.getMessage());
            System.out.println(e.getMessage());
        } finally {
            if (writer != null) {
                writer.close();
            }
        }
    }

    // 只对/api开头的api检测jwt
    private boolean isProtectedUrl(HttpServletRequest request) {
        return pathMatcher.match("/api/**", request.getServletPath());
    }

    /**
     * 过滤器销毁
     */
    @Override
    public void destroy() {
        log.info("JwtFilter destroy ...");
    }
}
